﻿using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Text;

namespace PmSoft.Core;

/// <summary>
/// 提供 JSON 序列化和反序列化的实用方法，支持可配置的设置。
/// </summary>
public static class Json
{
	/// <summary>
	/// 默认的 JSON 序列化设置，当未提供自定义设置时使用。
	/// </summary>
	private static readonly JsonSerializerSettings DefaultSettings = new()
	{
		NullValueHandling = NullValueHandling.Ignore, // 忽略空值
		DateFormatHandling = DateFormatHandling.MicrosoftDateFormat, // 使用 Microsoft 日期格式
		DateFormatString = "yyyy-MM-dd HH:mm:ss", // 日期格式字符串
		ContractResolver = new CamelCasePropertyNamesContractResolver(), // 属性名使用驼峰命名
		Formatting =
#if DEBUG
			Formatting.Indented // 调试模式下使用缩进格式
#else
            Formatting.None // 发布模式下无格式化
#endif
	};

 
	/// <summary>
	/// 将 JSON 字符串反序列化为指定类型的对象。
	/// </summary>
	/// <typeparam name="T">目标类型。</typeparam>
	/// <param name="json">要反序列化的 JSON 字符串。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>反序列化后的对象，如果失败则返回 default(T)。</returns>
	public static T? Parse<T>(string json, JsonSerializerSettings? settings = null)
	{
		return Parse<T>(json, typeof(T), settings);
	}

	/// <summary>
	/// 将 JSON 字符串反序列化为指定类型的对象，支持多态类型。
	/// </summary>
	/// <typeparam name="T">目标类型。</typeparam>
	/// <param name="json">要反序列化的 JSON 字符串。</param>
	/// <param name="type">反序列化的具体类型信息。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>反序列化后的对象，如果失败则返回 default(T)。</returns>
	public static T? Parse<T>(string json, Type type, JsonSerializerSettings? settings = null)
	{
		if (string.IsNullOrEmpty(json)) return default;

		settings ??= DefaultSettings;

		return (T?)Parse(json, type, settings);
	}

	/// <summary>
	/// 将 JSON 字符串反序列化为指定类型的对象。
	/// </summary>
	/// <param name="json">要反序列化的 JSON 字符串。</param>
	/// <param name="type">目标类型。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>反序列化后的对象，如果失败则返回 null。</returns>
	public static object? Parse(string json, Type type, JsonSerializerSettings? settings = null)
	{
		if (string.IsNullOrEmpty(json)) return null;
		settings ??= DefaultSettings;
		return JsonConvert.DeserializeObject(json, type, settings);
	}

	/// <summary>
	/// 将字节数组反序列化为指定类型的对象。
	/// </summary>
	/// <typeparam name="T">目标类型。</typeparam>
	/// <param name="bytes">包含 UTF-8 编码 JSON 的字节数组。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>反序列化后的对象，如果失败则返回 default(T)。</returns>
	public static T? Parse<T>(byte[]? bytes, JsonSerializerSettings? settings = null)
	{
		if (bytes == null || bytes.Length == 0) return default;
		var json = Encoding.UTF8.GetString(bytes);
		return Parse<T>(json, settings);
	}

	/// <summary>
	/// 将字节数组反序列化为指定类型的对象。
	/// </summary>
	/// <param name="bytes">包含 UTF-8 编码 JSON 的字节数组。</param>
	/// <param name="type">目标类型。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>反序列化后的对象，如果失败则返回 null。</returns>
	public static object? Parse(byte[]? bytes, Type type, JsonSerializerSettings? settings = null)
	{
		if (bytes == null || bytes.Length == 0) return null;
		var json = Encoding.UTF8.GetString(bytes);
		settings ??= DefaultSettings;
		return Parse(json, type, settings);
	}

	/// <summary>
	/// 将对象序列化为 JSON 字符串。
	/// </summary>
	/// <typeparam name="T">对象的类型。</typeparam>
	/// <param name="model">要序列化的对象。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>序列化后的 JSON 字符串。</returns>
	public static string Stringify<T>(T model, JsonSerializerSettings? settings = null)
	{
		settings ??= DefaultSettings;
		return JsonConvert.SerializeObject(model, settings);
	}

	/// <summary>
	/// 将字节数组序列化为 JSON 字符串。
	/// </summary>
	/// <typeparam name="T">对象的类型。</typeparam>
	/// <param name="serializedObject">要序列化的字节数组。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>序列化后的 JSON 字符串。</returns>
	public static string Stringify<T>(byte[] serializedObject, JsonSerializerSettings? settings = null)
	{
		settings ??= DefaultSettings;
		return JsonConvert.SerializeObject(serializedObject, settings);
	}

	/// <summary>
	/// 将对象序列化为字节数组。
	/// </summary>
	/// <typeparam name="T">对象的类型。</typeparam>
	/// <param name="model">要序列化的对象。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>序列化后的字节数组。</returns>
	public static byte[] Byteify<T>(T model, JsonSerializerSettings? settings = null)
	{
		var json = Stringify(model, settings);
		return Encoding.UTF8.GetBytes(json);
	}

	/// <summary>
	/// 将对象序列化为字节数组。
	/// </summary>
	/// <param name="model">要序列化的对象。</param>
	/// <param name="type">对象的类型。</param>
	/// <param name="settings">可选的自定义序列化设置。</param>
	/// <returns>序列化后的字节数组。</returns>
	public static byte[] Byteify(object model, Type type, JsonSerializerSettings? settings = null)
	{
		settings ??= DefaultSettings;
		var json = JsonConvert.SerializeObject(model, settings);
		return Encoding.UTF8.GetBytes(json);
	}
}